﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Agnes.TaskManager.Models;
using Csla;
using Agnes.Core;
using System.Xml.Linq;
using System.Collections.ObjectModel;
using Csla.Rules.CommonRules;

namespace Agnes.TaskManager
{
    /// <summary>
    /// 任务信息
    /// <remarks>
    ///     代表了任务管理中一条任务
    /// </remarks>
    /// </summary>
    [Serializable]
    public  class TaskInfo
        : ModelBase<TaskInfo>
    {
        #region Private

        private TaskInfo()
        { 

        }

        #endregion

        #region Csla Property

        #region Base Info

        ///<summary>
        ///CSLA Property Info # 
        /// <see cref="Id">
        /// See The Property : Id 
        /// </see>
        ///</summary>
        public static readonly PropertyInfo<Guid> IdProperty = RegisterProperty<Guid>(c => c.Id);
        ///<summary>
        ///[CSLA Property]:
        /// 任务唯一ID
        ///</summary>
        public Guid Id
        {
            get { return GetProperty(IdProperty); }
            set { SetProperty(IdProperty, value); }
        }

        ///<summary>
        ///CSLA Property Info #
        ///<see cref="TaskName">
        /// See The Property : TaskName
        ///</see>
        ///</summary>
        public static readonly PropertyInfo<string> TaskNameProperty = RegisterProperty<string>(c => c.TaskName);
        ///<summary>
        ///[CSLA Property]:
        ///任务名称
        ///</summary>
        public string TaskName
        {
            get { return GetProperty(TaskNameProperty); }
            set { SetProperty(TaskNameProperty, value); }
        }

        ///<summary>
        ///CSLA Property Info #
        ///<see cref="RegisterDT">
        /// See The Property : RegisterDT
        ///</see>
        ///</summary>
        public static readonly PropertyInfo<DateTime> RegisterDTProperty = RegisterProperty<DateTime>(c => c.RegisterDT);
        ///<summary>
        ///[CSLA Property]:
        ///登记时间
        ///</summary>
        public DateTime RegisterDT
        {
            get { return GetProperty(RegisterDTProperty); }
            set { SetProperty(RegisterDTProperty, value); }
        }

        ///<summary>
        ///CSLA Property Info #
        ///<see cref="DescriptionFile">
        /// See The Property : DescriptionFile
        ///</see>
        ///</summary>
        public static readonly PropertyInfo<string> DescriptionFileProperty = RegisterProperty<string>(c => c.DescriptionFile);
        ///<summary>
        ///[CSLA Property]:
        ///任务描述对应的文件路径
        ///</summary>
        public string DescriptionFile
        {
            get { return GetProperty(DescriptionFileProperty); }
            set { SetProperty(DescriptionFileProperty, value); }
        }

        ///<summary>
        ///CSLA Property Info #
        ///<see cref="PriorityLevel">
        /// See The Property : PriorityLevel
        ///</see>
        ///</summary>  
        public static readonly PropertyInfo<PriorityLevel> PriorityLevelProperty = RegisterProperty<PriorityLevel>(c => c.PriorityLevel);
        ///<summary>
        ///[CSLA Property]:
        ///优先级
        ///</summary>
        public PriorityLevel PriorityLevel
        {
            get { return GetProperty(PriorityLevelProperty); }
            set { SetProperty(PriorityLevelProperty, value); }
        }

        ///<summary>
        ///CSLA Property Info #
        ///<see cref="TaskFlag">
        /// See The Property : TaskFlag
        ///</see>
        ///</summary>
        public static readonly PropertyInfo<TaskFlag> TaskFlagProperty = RegisterProperty<TaskFlag>(c => c.TaskFlag);
        ///<summary>
        ///[CSLA Property]:
        ///任务类型标记
        ///</summary>
        public TaskFlag TaskFlag
        {
            get { return GetProperty(TaskFlagProperty); }
            set { SetProperty(TaskFlagProperty, value); }
        }

        ///<summary>
        ///CSLA Property Info #
        ///<see cref="DueDT">
        /// See The Property : DueDT
        ///</see>
        ///</summary>
        public static readonly PropertyInfo<DateTime> DueDTProperty = RegisterProperty<DateTime>(c => c.DueDT);
        ///<summary>
        ///[CSLA Property]:
        ///到期时间
        ///</summary>
        public DateTime DueDT
        {
            get { return GetProperty(DueDTProperty); }
            set { SetProperty(DueDTProperty, value); }
        }

        ///<summary>
        ///CSLA Property Info #
        ///<see cref="ChildTasks">
        /// See The Property : ChildTasks
        ///</see>
        ///</summary>
        public static readonly PropertyInfo<ObservableCollection<TaskInfo>> ChildTasksProperty = RegisterProperty<ObservableCollection<TaskInfo>>(c => c.ChildTasks);
        ///<summary>
        ///[CSLA Property]:
        ///子任务列表
        ///</summary>
        public ObservableCollection<TaskInfo> ChildTasks
        {
            get { return GetProperty(ChildTasksProperty); }
            private set { SetProperty(ChildTasksProperty, value); }
        }


        /// <summary>
        /// 父节点 如果没有父节点则为null
        /// </summary>
        public TaskInfo Parent { get; private set; }

        #endregion

        #region CirculateInfo

        ///<summary>        
        ///CSLA Property Info #
        ///<see cref="EnableCirculate">
        /// See The Property : EnableCirculate
        ///</see>
        ///</summary>
        public static readonly PropertyInfo<bool> EnableCirculateProperty = RegisterProperty<bool>(c => c.EnableCirculate);
        ///<summary>
        ///[CSLA Property]:
        ///是否启用循环模式
        ///</summary>
        public bool EnableCirculate
        {
            get { return GetProperty(EnableCirculateProperty); }
            set { SetProperty(EnableCirculateProperty, value); }
        }

        ///<summary>
        ///CSLA Property Info #
        ///<see cref="CirculateInfo">
        /// See The Property : CirculateInfo
        ///</see>
        ///</summary>
        public static readonly PropertyInfo<CirculateInfo> CirculateInfoProperty = RegisterProperty<CirculateInfo>(c => c.CirculateInfo, RelationshipTypes.Child);
        ///<summary>
        ///[CSLA Property]:
        ///循环任务信息(当且仅当EnableCirculate=true的时候该参数有效)
        ///</summary>
        public CirculateInfo CirculateInfo
        {
            get { return GetProperty(CirculateInfoProperty); }
            private set { SetProperty(CirculateInfoProperty, value); }
        }



        #endregion

        #endregion
        
        #region Csla Method

        private XElement GetXml()
        {
            XElement el = new XElement("TaskInfo",
                new XAttribute("Id", Id.ToString()),
                new XAttribute("TaskName", TaskName),
                new XAttribute("RegisterDT", RegisterDT),
                new XAttribute("DescriptionFile", DescriptionFile),
                new XAttribute("PriorityLevel", PriorityLevel),
                new XAttribute("TaskFlag", TaskFlag),
                new XAttribute("EnableCirculate", EnableCirculate));
                CirculateInfo.SaveToXml(t => el.Add(t));

                foreach (TaskInfo i in ChildTasks)
                    i.SaveToXml(t => el.Add(t));

            return el;
        }

        /// <summary>
        /// 新建对象
        /// </summary>
        /// <param name="createParam">null</param>
        protected override void  DoCreate(object createParam)
        {
 	        base.DoCreate(createParam);
            using (BypassPropertyChecks)
            {
                Id = Guid.NewGuid();
                TaskName = "";
                RegisterDT = DateTime.Now;
                DueDT = DateTime.Now.AddDays(1);
                DescriptionFile = "";
                PriorityLevel = PriorityLevel.Medium;
                TaskFlag = TaskFlag.FlagCatalog;
                ChildTasks = new ObservableCollection<TaskInfo>();
                EnableCirculate = false;
                CirculateInfo = CirculateInfo.CreateAsChild();
            }
        }

        /// <summary>
        /// 加载对象
        /// </summary>
        /// <param name="fetchParam">XElement</param>
        protected override void DoFetch(object fetchParam)
        {
            base.DoFetch(fetchParam);
            using (BypassPropertyChecks)
            {
                XElement el = fetchParam as XElement;
                Id = Guid.Parse(el.Attribute("Id").Value);
                TaskName = el.Attribute("TaskName").Value;
                RegisterDT = DateTime.Parse(el.Attribute("RegisterDT").Value);
                DescriptionFile = el.Attribute("DescriptionFile").Value;
                PriorityLevel = (PriorityLevel)Enum.Parse(typeof(PriorityLevel),
                    el.Attribute("PriorityLevel").Value);
                TaskFlag = (TaskFlag)Enum.Parse(typeof(TaskFlag),el.Attribute("TaskFlag").Value);
                EnableCirculate = Boolean.Parse(el.Attribute("EnableCirculate").Value);
                CirculateInfo = CirculateInfo.FetchAsChild(el.Element("CirculateInfo"));
                ChildTasks = new ObservableCollection<TaskInfo>();
                foreach(XElement i in el.Elements("TaskInfo"))
                    ChildTasks.Add(TaskInfo.FetchAsChild(i));
            }
        }

        /// <summary>
        /// 保存到XML
        /// </summary>
        /// <param name="saveFunc">t=>[XElment].add(t)</param>
        public void SaveToXml(Action<XElement> saveFunc)
        {
            base.Save(true);
            saveFunc(GetXml());
            DataPortal_Update();
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void AddBusinessRules()
        {
            base.AddBusinessRules();

            AddTaskNameRule();
        }

        #endregion

        #region Csla Validation

        private void AddTaskNameRule()
        {
            var r = new Lambda(TaskNameProperty, t =>
                {
                    TaskInfo h = t.Target as TaskInfo;
                    if (h.TaskName == "")
                        t.AddErrorResult("任务名不能为空");
                    else if (h.TaskName.Contains("/"))
                        t.AddErrorResult("任务名不能包含分隔符:/");
                    else
                    {
                        if (Parent != null)
                        {
                            foreach (TaskInfo i in Parent.ChildTasks)
                            {
                                if (i.TaskName == h.TaskName)
                                    t.AddErrorResult(TaskName + " 同级任务中已经存在!");
                            }
                        }
                        else
                        {
                            foreach (TaskInfo i in TaskManager.Instance.TaskRoots)
                            {
                                if (i.TaskName == h.TaskName)
                                    t.AddErrorResult(TaskName + " 同级任务中已经存在!");
                            }
                        }
                    }
                });

            BusinessRules.AddRule(r);
        }

        #endregion

        #region Method

        /// <summary>
        /// 添加一个子任务
        /// </summary>
        /// <param name="taskInfo"></param>
        public void AddSubTask(TaskInfo taskInfo)
        {
            taskInfo.Parent = this;
        }

        /// <summary>
        /// 获得该任务在整个任务树中的路径,不包括本身
        /// </summary>
        public void GetTreePath()
        {
            TaskInfo tmp = this;
            string res = "/";
            while (tmp.Parent != null)
            {
                res = "/" + tmp.Parent.TaskName + res;
                tmp = tmp.Parent;
            }
        }

        #endregion
    }
}
